package com.tjetc.ioc.controller;

import com.tjetc.ioc.dao.UserDao;
import com.tjetc.ioc.service.UserService;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

/**
 * @author gaoyongxiang
 * @version v1.0
 * @date 2025/9/1
 */
//@Controller
// 如果写了注解中的value属性 则按照写的名称进行注入 如果不写 则按照类名的首字母小写进行注入
@Component
// 这个注解可以控制单例还是多例 不写默认是单例 一般我们都是单例 不需要修改
//@Scope("prototype")
public class UserController implements InitializingBean {

    // 初始化方法的返回值必须是void 执行时机是在bean创建对象之前被执行
    // 该方法在构造方法之后执行
    @PostConstruct
    public void initMethod(){
        System.out.println("initMethod执行");
    }

    // 一般不使用
    // Spring会对单例对象管理销毁的生命周期
    @PreDestroy
    public void destroyMethod(){
        System.out.println("destroyMethod执行");
    }


    public UserController() {
        System.out.println("UserController初始化");
    }

    // 自动注入 如果我们写的代码比较规范 这两个无所谓

    /**
     *
     * 1. 基于注解配置bean，也可实现自动装配，使用的注解是：@AutoWired 或者 @Resource
     * 2. @AutoWired 的规则说明
     * 1) 在IOC容器中查找待装配的组件的类型，如果有唯一的bean匹配 ，则使用该bean装配和定义的属性名称无关
     * 2) 如待装配的类型对应的bean在IOC容器中有多个，则使用待装配的属性的属性名作为id值再进行查找,找到就装配,找不到就抛异常
     * 3. @Resource 的规则说明
     * 1) @Resource 有两个属性是比较重要的,分别是 name 和 type,Spring 将@Resource 注解的name属性解析为bean的名字,而type属性则解析为bean的类型.
     * 所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略
     * 2) 如果@Resource 没有指定 name 和 type ,则先使用 byName 注入策略, 如果匹配不上, 再使用 byType 策略, 如果都不成功 ，就会报错
     * <p>
     * 4. 不管是@Autowired 还是 @Resource 都保证属性名是规范的写法就可以注入
     */

    /*
        Unsatisfied dependency expressed through field 'userService':
        No qualifying bean of type 'com.tjetc.ioc.service.UserService' available:
            expected single matching bean but found 2: userServiceImpl,userServiceImpl1

        Injection of resource dependencies failed

     */



//    @Autowired
//    @Qualifier("userServiceImpl1")
//    private UserService userService;
//    private UserService userServiceImpl1;

    @Resource(name = "userServiceImpl1")
    private UserService userService;

    // 这种方式注入 是官方推荐注入 有很多的好处
    // 但是写起来比较麻烦 所以我们很少用 在生产环境中应该使用这种
//    public UserController(UserService userService) {
//        this.userService = userService;
//    }

    public void f() {
        userService.f();
//        userServiceImpl1.f();

    }

    // 这个方法会在@PostConstruct定义的方法之后执行
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet执行");
    }
}